package cn.zhaozhiqi.service.impl;

import cn.zhaozhiqi.constants.Constants;
import cn.zhaozhiqi.exception.GlobalException;
import cn.zhaozhiqi.pojo.AliPayDto;
import cn.zhaozhiqi.pojo.domain.PayOrder;
import cn.zhaozhiqi.pojo.domain.WxpayFlow;
import cn.zhaozhiqi.pojo.dto.AlipayNotifyDto;
import cn.zhaozhiqi.pojo.mq.dto.PayMQDto;
import cn.zhaozhiqi.service.IPayOrderService;
import cn.zhaozhiqi.service.IPayService;
import cn.zhaozhiqi.template.AliPayTemplate;
import cn.zhaozhiqi.utils.AssertUtil;
import com.alibaba.fastjson.JSON;
import com.alipay.easysdk.factory.Factory;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.client.producer.TransactionSendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;


@Service
@Slf4j
public class PayServiceImpl implements IPayService {
    @Autowired
    private IPayOrderService payOrderService;
    @Autowired
    private AliPayTemplate aliPayTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;


    /**
     * 支付宝的异步回调
     * @param dto
     * @return
     */
    @Override
    public String alipayNotify(AlipayNotifyDto dto) {
        String jsonString = JSON.toJSONString(dto);
        Map<String, String> map = JSON.parseObject(jsonString, Map.class);
//... ... 接收到的所有参数放入一个Map中
        try {
            Boolean verifyNotify = Factory.Payment.Common().verifyNotify(map);
            if (!verifyNotify) {
                return "no";
            }
            if (dto.getTrade_status() != AlipayNotifyDto.TRADE_SUCCESS) {
                return "no";
            }
            //代码执行到这里，说明OK了 处理我们的业务逻辑
            String orderNo = dto.getOut_trade_no();
            PayOrder payOrder = payOrderService.getByOrderNo(orderNo);
            if (payOrder == null) {
                return "no";
            }
            if (payOrder.getPayStatus() != Constants.PayStatus.WATTING) {
                return "success";//直接签收消息
            }
            //一：处理Service-pay的业务逻辑
            //1.统一支付单状态
            payOrder.setPayStatus(Constants.PayStatus.PAY_SUCCESS);
            payOrder.setSuccessPayTime(new Date());
            payOrder.setPayOrderNo(dto.getTrade_no());//支付宝的交易号
            //payOrderService.updateById(payOrder); //交给事务消息保存
            //2.记录流水
            WxpayFlow flow = new WxpayFlow();
            flow.setAmount(payOrder.getAmount());
            flow.setOutTradeNo(payOrder.getPayOrderNo());
            flow.setPayerOpenid(payOrder.getPayOpenId());
            flow.setUserId(payOrder.getPayUserId());
            flow.setSuccessTime(payOrder.getSuccessPayTime());
            flow.setTradeState(dto.getTrade_status());
            //wxpayFlowService.save(flow);  //交给事务消息保存

            //二：处理Order和driver的业务逻辑  发送事务消息，消费方通过广播模式消费消息即可
            HashMap<String, Object> mapObj = new HashMap<String, Object>();
            mapObj.put("payOrder", payOrder);
            mapObj.put("flow", flow);
            PayMQDto payMQDto = new PayMQDto();
            payMQDto.setDriverId(payOrder.getDriverId());
            payMQDto.setOrderNo(payOrder.getOrderNo());
            Message<PayMQDto> message = MessageBuilder.withPayload(payMQDto).build();
            //发送事务消息
            TransactionSendResult sendResult = rocketMQTemplate.sendMessageInTransaction(
                    Constants.Mq.PAY_SUCCESS_GROUP,
                    Constants.Mq.TOPIC_PAY_SUCCESS + ":" + Constants.Mq.TAG_PAY_SUCCESS,
                    message,
                    mapObj
            );

            if (sendResult.getSendStatus() != SendStatus.SEND_OK) {
                //消息兜底
                throw new GlobalException("发送支付成功消息失败！");
            }

            return "success";
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
        /**
     * 调用支付宝支付的方法
     * 1.根据orderNo查询统一支付单，并且必须是待支付状态
     * 2.使用封装好的starter触发支付逻辑
     * 3.返回前端
     * 4.等待回调（再写一个接口）
     * @param orderNo
     * @param payType  支付方式
     * @return
     */
    @Override
    public Object alipay(String orderNo,Integer payType) {
        //调用阿里pay支付
        if (payType.equals(Constants.PayType.ALIPAY)){
            executeAlipay(orderNo);
        }
        //调用微信支付
        if (payType.equals(Constants.PayType.WECHAT)){

        }


        return null;
    }




    /**
     * 支付宝支付
     *  1.根据OrderNo查询出统一支付单
     *  2.判断状态，必须是待支付
     *  3.封装支付starter ，触发支付逻辑，等待响应
     *  4.甩给前端
     *
     *  5.编写异步通知接口，坐等回调，处理支付成功业务
     * @param orderNo
     */
    private void executeAlipay(String orderNo) {
        PayOrder payOrder = payOrderService.getByOrderNo(orderNo);
        AssertUtil.isNotNull(payOrder,"支付异常，支付单不存在！");
        AssertUtil.isEquals(payOrder.getPayStatus(),Constants.PayStatus.WATTING,"支付异常，支付单状态异常！");
        AliPayDto aliPayDto = new AliPayDto();
        aliPayDto.setSubject(payOrder.getSubject());
        aliPayDto.setOutTradeNo(payOrder.getOrderNo());
        aliPayDto.setTotalAmount(payOrder.getAmount().toString());
        aliPayDto.setReturnUrl("https://www.baidu.com");
        payOrder.setApplyPayTime(new Date());
        payOrderService.updateById(payOrder);

        String alipayRes = aliPayTemplate.aliPay(aliPayDto);
        log.info("支付宝支付成功！");
        System.out.println(alipayRes);

    }

    /**
     * 根据传入的订单号和统一支付单状态来拿到订单
     * @param orderNo
     * @return
     */
    public PayOrder getPayOrderByOrderNo(String orderNo){
        return payOrderService.getOne(new LambdaQueryWrapper<PayOrder>()
                .eq(PayOrder::getOrderNo,orderNo));
    }
}
